#include "IRgen.h"
#include "../include/ir.h"
#include "semant.h"

extern SemantTable semant_table;    // 也许你会需要一些语义分析的信息
std::map<FuncDefInstruction, int> max_label_map{};
std::map<FuncDefInstruction, int> max_reg_map{};
IRgenTable irgen_table;    // 中间代码生成的辅助变量
LLVMIR llvmIR;             // 我们需要在这个变量中生成中间代码

static FuncDefInstruction now_function;//记录现在处在的函数
static int now_label = 0;//记录现在处在的标签位置

int max_reg = -1;//寄存器号用到几号了
int max_label = -1;//标签号用到几号了


//由节点的type转成LLVMType
BasicInstruction::LLVMType type2LLVMType(Type::ty t){
    if(t==Type::INT){
        return BasicInstruction::LLVMType::I32;
    }
    else if(t==Type::FLOAT){
        return BasicInstruction::LLVMType::FLOAT32;
    }
    else if(t==Type::BOOL){
        return BasicInstruction::LLVMType::I1;
    }
    else if(t==Type::PTR){
        return BasicInstruction::LLVMType::PTR;
    }
    else if(t==Type::VOID){
        return BasicInstruction::LLVMType::VOID;
    }
    else if(t==Type::DOUBLE){
        return BasicInstruction::LLVMType::DOUBLE;
    }
}

// 添加类型转换函数
BasicInstruction::LLVMType convertTyToLLVMType(Type::ty type) {
    switch(type) {
        case Type::INT: return BasicInstruction::I32;
        case Type::FLOAT: return BasicInstruction::FLOAT32;
        case Type::BOOL: return BasicInstruction::I1;
        case Type::VOID: return BasicInstruction::VOID;
        case Type::PTR: return BasicInstruction::PTR;
        default: return BasicInstruction::VOID;
    }
}

static std::stack<std::pair<int, int>> loop_labels; // 存储 <true_label, false_label>

void AddLibFunctionDeclare();

// 在基本块B末尾生成一条新指令
void IRgenArithmeticI32(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, int reg1, int reg2, int result_reg);
void IRgenArithmeticF32(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, int reg1, int reg2, int result_reg);
void IRgenArithmeticI32ImmLeft(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, int val1, int reg2, int result_reg);
void IRgenArithmeticF32ImmLeft(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, float val1, int reg2,
                               int result_reg);
void IRgenArithmeticI32ImmAll(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, int val1, int val2, int result_reg);
void IRgenArithmeticF32ImmAll(LLVMBlock B, BasicInstruction::LLVMIROpcode opcode, float val1, float val2,
                              int result_reg);

void IRgenIcmp(LLVMBlock B, BasicInstruction::IcmpCond cmp_op, int reg1, int reg2, int result_reg);
void IRgenFcmp(LLVMBlock B, BasicInstruction::FcmpCond cmp_op, int reg1, int reg2, int result_reg);
void IRgenIcmpImmRight(LLVMBlock B, BasicInstruction::IcmpCond cmp_op, int reg1, int val2, int result_reg);
void IRgenFcmpImmRight(LLVMBlock B, BasicInstruction::FcmpCond cmp_op, int reg1, float val2, int result_reg);

void IRgenFptosi(LLVMBlock B, int src, int dst);
void IRgenSitofp(LLVMBlock B, int src, int dst);
void IRgenZextI1toI32(LLVMBlock B, int src, int dst);

void IRgenGetElementptrIndexI32(LLVMBlock B, BasicInstruction::LLVMType type, int result_reg, Operand ptr,
                        std::vector<int> dims, std::vector<Operand> indexs);

void IRgenGetElementptrIndexI64(LLVMBlock B, BasicInstruction::LLVMType type, int result_reg, Operand ptr,
                        std::vector<int> dims, std::vector<Operand> indexs);

void IRgenLoad(LLVMBlock B, BasicInstruction::LLVMType type, int result_reg, Operand ptr);
void IRgenStore(LLVMBlock B, BasicInstruction::LLVMType type, int value_reg, Operand ptr);
void IRgenStore(LLVMBlock B, BasicInstruction::LLVMType type, Operand value, Operand ptr);

void IRgenCall(LLVMBlock B, BasicInstruction::LLVMType type, int result_reg,
               std::vector<std::pair<enum BasicInstruction::LLVMType, Operand>> args, std::string name);
void IRgenCallVoid(LLVMBlock B, BasicInstruction::LLVMType type,
                   std::vector<std::pair<enum BasicInstruction::LLVMType, Operand>> args, std::string name);

void IRgenCallNoArgs(LLVMBlock B, BasicInstruction::LLVMType type, int result_reg, std::string name);
void IRgenCallVoidNoArgs(LLVMBlock B, BasicInstruction::LLVMType type, std::string name);

void IRgenRetReg(LLVMBlock B, BasicInstruction::LLVMType type, int reg);
void IRgenRetImmInt(LLVMBlock B, BasicInstruction::LLVMType type, int val);
void IRgenRetImmFloat(LLVMBlock B, BasicInstruction::LLVMType type, float val);
void IRgenRetVoid(LLVMBlock B);

void IRgenBRUnCond(LLVMBlock B, int dst_label);
void IRgenBrCond(LLVMBlock B, int cond_reg, int true_label, int false_label);

void IRgenAlloca(LLVMBlock B, BasicInstruction::LLVMType type, int reg);
void IRgenAllocaArray(LLVMBlock B, BasicInstruction::LLVMType type, int reg, std::vector<int> dims);

RegOperand *GetNewRegOperand(int RegNo);

// generate TypeConverse Instructions from type_src to type_dst
// eg. you can use fptosi instruction to converse float to int
// eg. you can use zext instruction to converse bool to int
//负责进行数据类型转换的函数
void IRgenTypeConverse(LLVMBlock B, Type::ty type_src, Type::ty type_dst, int src) {
    //TODO("IRgenTypeConverse. Implement it if you need it");
    if (type_src == type_dst) {
        return;
    }
    if (type_src == Type::INT && type_dst == Type::FLOAT) {
        IRgenSitofp(B, src, ++max_reg);
    } else if (type_src == Type::INT && type_dst == Type::BOOL) {
        //不为0的bool为1，为0的bool为0
        IRgenIcmpImmRight(B, BasicInstruction::IcmpCond::ne, src, 0, ++max_reg);
    } else if (type_src == Type::FLOAT && type_dst == Type::INT) {
        IRgenFptosi(B, src, ++max_reg);
    } else if (type_src == Type::FLOAT && type_dst == Type::BOOL) {
        IRgenFcmpImmRight(B, BasicInstruction::FcmpCond::ONE, src, 0, ++max_reg);
    } else if (type_src == Type::BOOL && type_dst == Type::INT) {
        IRgenZextI1toI32(B, src, ++max_reg);
    } else if (type_src == Type::BOOL && type_dst == Type::FLOAT) {
        //bool->int->float
        IRgenZextI1toI32(B, src, ++max_reg);
        src = max_reg;
        IRgenSitofp(B, src, ++max_reg);
    } else if (type_src == Type::FLOAT && type_dst == Type::DOUBLE) {
        //IRgenFpext(B, src, ++max_reg);
    } else {
        assert(false);
    }
}

void BasicBlock::InsertInstruction(int pos, Instruction Ins) {
    assert(pos == 0 || pos == 1);
    if (pos == 0) {
        Instruction_list.push_front(Ins);
    } else if (pos == 1) {
        Instruction_list.push_back(Ins);
    }
}
//reference:https://github.com/yuhuifishash/SysY/blob/master/ir_gen/IRgen.cc line527-line591
int FindMinDimStepIR(const std::vector<int> dims, int relativePos, int dimsIdx, int &max_subBlock_sz) {
    int min_dim_step = 1;
    int blockSz = 1;
    for (int i = dimsIdx + 1; i < dims.size(); i++) {
        blockSz *= dims[i];
    }
    while (relativePos % blockSz != 0) {
        min_dim_step++;
        blockSz /= dims[dimsIdx + min_dim_step - 1];
    }
    max_subBlock_sz = blockSz;
    std::cout<<"inFindMinDimStepIR max_subBlock_sz:"<<max_subBlock_sz<<std::endl;
    std::cout<<"inFindMinDimStepIR min_dim_step:"<<min_dim_step<<std::endl;
    std::cout<<"inFindMinDimStepIR relativePos:"<<relativePos<<std::endl;
    std::cout<<"inFindMinDimStepIR dimsIdx:"<<dimsIdx<<std::endl;
    return min_dim_step;
}
std::vector<int> GetIndexes(std::vector<int> dims, int absoluteIndex) {
    //[3][4]
    // 0-> {0,0}  {absoluteIndex/4,absoluteIndex%4}
    // 1-> {0,1}
    // 2-> {0,2}
    // 3-> {0,3}
    // 4-> {1,0}
    // 5-> {1,1}
    std::vector<int> ret;
    for (std::vector<int>::reverse_iterator it = dims.rbegin(); it != dims.rend(); ++it) {
        int dim = *it;
        ret.insert(ret.begin(), absoluteIndex % dim);
        absoluteIndex /= dim;
    }
    return ret;
}
//reference:https://github.com/yuhuifishash/SysY/blob/master/ir_gen/IRgen.cc line527-line591
void RecursiveArrayInitIR(LLVMBlock block, const std::vector<int> dims, int arrayaddr_reg_no, InitVal init,
                          int beginPos, int endPos, int dimsIdx, Type::ty ArrayType) {
    int pos = beginPos;
    for (InitVal iv : *(init->GetList())) {
        if (iv->IsExp()) {
            iv->codeIR();
            int init_val_reg = max_reg;
            IRgenTypeConverse(block, iv->attribute.T.type, ArrayType, init_val_reg);
            init_val_reg = max_reg;

            int addr_reg = ++max_reg;
             std::vector<int> indexes = GetIndexes(dims, pos);
             std::cout<<"inRecursiveArrayInitIR indexes:"<<std::endl;
             for(int idx : indexes) {
                std::cout<<idx<<" ";
             }
             std::cout<<std::endl;  
             std::cout<<"inRecursiveArrayInitIR init:"<<iv->attribute.V.val.IntVal<<std::endl;
             std::vector<Operand> indexOperands;    
            indexOperands.push_back(new ImmI32Operand(0)); // 添加初始0偏移
            for(int idx : indexes) {
                indexOperands.push_back(new ImmI32Operand(idx));
            }
            //auto gep= convertTyToLLVMType(ArrayType);
            IRgenGetElementptrIndexI32(block,convertTyToLLVMType(ArrayType), addr_reg,
                                                    GetNewRegOperand(arrayaddr_reg_no), dims, indexOperands);
            
            IRgenStore(block, convertTyToLLVMType(ArrayType), GetNewRegOperand(init_val_reg), GetNewRegOperand(addr_reg));
            pos++;
        } else {
            std::cout<<"inRecursiveArrayInitIR pos:"<<pos<<std::endl;
            std::cout<<"inRecursiveArrayInitIR beginPos:"<<beginPos<<std::endl;
            std::cout<<"inRecursiveArrayInitIR endPos:"<<endPos<<std::endl;

            int max_subBlock_sz = 0;
            int min_dim_step = FindMinDimStepIR(dims, pos - beginPos, dimsIdx, max_subBlock_sz);
            RecursiveArrayInitIR(block, dims, arrayaddr_reg_no, iv, pos, pos + max_subBlock_sz - 1,dimsIdx + min_dim_step, ArrayType);
            pos += max_subBlock_sz;
        }
    }
}

//______________________________________________________
//下面是处理基本的表达式

//二元表达式

//已知两个子节点的类型和操作数，就可以去生成具体的指令了
//处理int
void binary_int_add(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticI32(B, BasicInstruction::LLVMIROpcode::ADD, reg1, reg2, ++max_reg);
}

void binary_int_sub(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticI32(B, BasicInstruction::LLVMIROpcode::SUB, reg1, reg2, ++max_reg);
}

void binary_int_mul(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticI32(B, BasicInstruction::LLVMIROpcode::MUL, reg1, reg2, ++max_reg);
}

void binary_int_div(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticI32(B, BasicInstruction::LLVMIROpcode::DIV, reg1, reg2, ++max_reg);
}

void binary_int_mod(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticI32(B, BasicInstruction::LLVMIROpcode::MOD, reg1, reg2, ++max_reg);
}

void binary_int_leq(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::sle, reg1, reg2, ++max_reg); 
}

void binary_int_lt(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::slt, reg1, reg2, ++max_reg); 
}

void binary_int_geq(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::sge, reg1, reg2, ++max_reg); 
}

void binary_int_gt(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::sgt, reg1, reg2, ++max_reg); 
}

void binary_int_eq(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::eq, reg1, reg2, ++max_reg); 
}

void binary_int_neq(int reg1,int reg2, LLVMBlock B){
    IRgenIcmp(B, BasicInstruction::IcmpCond::ne, reg1, reg2, ++max_reg); 
}

//处理float
void binary_float_add(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticF32(B,BasicInstruction::LLVMIROpcode::FADD,reg1,reg2,++max_reg);
}

void binary_float_sub(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticF32(B,BasicInstruction::LLVMIROpcode::FSUB,reg1,reg2,++max_reg);
}

void binary_float_mul(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticF32(B,BasicInstruction::LLVMIROpcode::FMUL,reg1,reg2,++max_reg);
}

void binary_float_div(int reg1,int reg2, LLVMBlock B){
    IRgenArithmeticF32(B,BasicInstruction::LLVMIROpcode::FDIV,reg1,reg2,++max_reg);
}

void binary_float_mod(int reg1,int reg2, LLVMBlock B){
    assert(false); 
}

void binary_float_leq(int reg1,int reg2, LLVMBlock B){
    //有序条件会检查操作数是否为NaN，而无序条件则不会。这在浮点数比较中非常重要，因为NaN与任何值（包括它自己）的比较结果都是未定义的。
    IRgenFcmp(B,BasicInstruction::FcmpCond::OLE,reg1,reg2,++max_reg);
}

void binary_float_lt(int reg1,int reg2, LLVMBlock B){
    IRgenFcmp(B, BasicInstruction::FcmpCond::OLT, reg1, reg2, ++max_reg); 
}

void binary_float_geq(int reg1,int reg2, LLVMBlock B){
    IRgenFcmp(B, BasicInstruction::FcmpCond::OGE, reg1, reg2, ++max_reg); 
}

void binary_float_gt(int reg1,int reg2, LLVMBlock B){
    IRgenFcmp(B, BasicInstruction::FcmpCond::OGT, reg1, reg2, ++max_reg); 
}

void binary_float_eq(int reg1,int reg2, LLVMBlock B){
    IRgenFcmp(B, BasicInstruction::FcmpCond::OEQ, reg1, reg2, ++max_reg); 
}

void binary_float_neq(int reg1,int reg2, LLVMBlock B){
    IRgenFcmp(B, BasicInstruction::FcmpCond::ONE, reg1, reg2, ++max_reg); 
}



//知道了两个节点的类型，还需要根据运算符op来决定生成什么指令
void binary_int_int_op(int reg1,int reg2,std::string op, LLVMBlock B){
    if(op=="+"){
        binary_int_add(reg1,reg2,B);
    }
    else if(op=="-"){
        binary_int_sub(reg1,reg2,B);
    }
    else if(op=="*"){
        binary_int_mul(reg1,reg2,B);
    }
    else if(op=="/"){
        binary_int_div(reg1,reg2,B);
    }
    else if(op=="%"){
        binary_int_mod(reg1,reg2,B);
    }
    else if(op=="<="){
        binary_int_leq(reg1,reg2,B);
    }
    else if(op=="<"){
        binary_int_lt(reg1,reg2,B);
    }
    else if(op==">="){
        binary_int_geq(reg1,reg2,B);
    }
    else if(op==">"){
        binary_int_gt(reg1,reg2,B);
    }
    else if(op=="=="){
        binary_int_eq(reg1,reg2,B);
    }
    else if(op=="!="){
        binary_int_neq(reg1,reg2,B);
    }
}

void binary_float_float_op(int reg1,int reg2,std::string op, LLVMBlock B){
    if(op=="+"){
        binary_float_add(reg1,reg2,B);
    }
    else if(op=="-"){
        binary_float_sub(reg1,reg2,B);
    }
    else if(op=="*"){
        binary_float_mul(reg1,reg2,B);
    }
    else if(op=="/"){
        binary_float_div(reg1,reg2,B);
    }
    else if(op=="%"){
        binary_float_mod(reg1,reg2,B);
    }
    else if(op=="<="){
        binary_float_leq(reg1,reg2,B);
    }
    else if(op=="<"){
        binary_float_lt(reg1,reg2,B);
    }
    else if(op==">="){
        binary_float_geq(reg1,reg2,B);
    }
    else if(op==">"){
        binary_float_gt(reg1,reg2,B);
    }
    else if(op=="=="){
        binary_float_eq(reg1,reg2,B);
    }
    else if(op=="!="){
        binary_float_neq(reg1,reg2,B);
    }
}



void binary_int_int(Expression a,Expression b,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;//这个寄存器存的是节点a的结果
    b->codeIR();
    int reg2 = max_reg;//这个寄存器存的是节点b的结果
    binary_int_int_op(reg1,reg2,op,B);
}

void binary_int_float(Expression a,Expression b,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenSitofp(B, reg1, ++max_reg);    // 把a由int->float
    reg1 = max_reg;
    binary_float_float_op(reg1,reg2,op,B);
}

void binary_int_bool(Expression a,Expression b,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenZextI1toI32(B,reg2,++max_reg);// 把b由bool->int
    reg2 = max_reg;
    binary_int_int_op(reg1,reg2,op,B);
}

void binary_float_int(Expression a,Expression b,std::string op, LLVMBlock B) {
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenSitofp(B, reg2, ++max_reg);    //把b由int->float
    reg2 = max_reg;
    binary_float_float_op(reg1,reg2,op,B);
}

void binary_float_float(Expression a,Expression b,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;//这个寄存器存的是节点a的结果
    b->codeIR();
    int reg2 = max_reg;//这个寄存器存的是节点b的结果
    binary_float_float_op(reg1,reg2,op,B);
}

void binary_float_bool(Expression a,Expression b,std::string op, LLVMBlock B) {
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenZextI1toI32(B, reg2, ++max_reg);    // 把b由bool -> int->float
    reg2 = max_reg;
    IRgenSitofp(B, reg2, ++max_reg);
    reg2 = max_reg;
    binary_float_float_op(reg1,reg2,op,B);
}

void binary_bool_int(Expression a,Expression b,std::string op, LLVMBlock B) {
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenZextI1toI32(B, reg1, ++max_reg);    //把a由bool -> int
    reg1 = max_reg;
    binary_int_int_op(reg1,reg2,op,B);
}

void binary_bool_float(Expression a,Expression b,std::string op, LLVMBlock B) {
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenZextI1toI32(B, reg1, ++max_reg);    //把a由bool -> int->float
    reg1 = max_reg;
    IRgenSitofp(B, reg1, ++max_reg);    
    reg1 = max_reg;
    binary_float_float_op(reg1,reg2,op,B);
}

void binary_bool_bool(Expression a,Expression b,std::string op, LLVMBlock B) {
    a->codeIR();
    int reg1 = max_reg;
    b->codeIR();
    int reg2 = max_reg;
    IRgenZextI1toI32(B, reg1, ++max_reg);    // 把a由bool -> int
    reg1 = max_reg;
    IRgenZextI1toI32(B, reg2, ++max_reg);    // 把a由bool -> int
    reg2 = max_reg;
    binary_int_int_op(reg1,reg2,op,B);
}

void binary_error(Expression a,Expression b,std::string op, LLVMBlock B) { 
    assert(false); 
}


//这个函数根据两个节点的类型来处理
void gen_binary_IR(Expression a,Expression b,std::string op, LLVMBlock B){
    if(a->attribute.T.type==Type::INT&&b->attribute.T.type==Type::INT){
        binary_int_int(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::INT&&b->attribute.T.type==Type::FLOAT){
        binary_int_float(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::INT&&b->attribute.T.type==Type::BOOL){
        binary_int_bool(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::FLOAT&&b->attribute.T.type==Type::INT){
        binary_float_int(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::FLOAT&&b->attribute.T.type==Type::FLOAT){
        binary_float_float(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::FLOAT&&b->attribute.T.type==Type::BOOL){
        binary_float_bool(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::BOOL&&b->attribute.T.type==Type::INT){
        binary_bool_int(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::BOOL&&b->attribute.T.type==Type::FLOAT){
        binary_bool_float(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::BOOL&&b->attribute.T.type==Type::BOOL){
        binary_bool_bool(a,b,op,B);
    }
    else if(a->attribute.T.type==Type::PTR||a->attribute.T.type==Type::VOID||b->attribute.T.type==Type::PTR||b->attribute.T.type==Type::VOID){
        binary_error(a,b,op,B);
    }

}




//下面处理单目运算

void single_int_add(int reg1, LLVMBlock B){
    //IRgenArithmeticI32ImmLeft(B, BasicInstruction::LLVMIROpcode::ADD, 0, reg1, ++max_reg);
    //好像没必要再写一条指令
}

void single_int_sub(int reg1, LLVMBlock B){
    //0-reg1，左操作数为立即数
    IRgenArithmeticI32ImmLeft(B, BasicInstruction::LLVMIROpcode::SUB, 0, reg1, ++max_reg);
}

void single_int_not(int reg1, LLVMBlock B){
    //reg1==0
    IRgenIcmpImmRight(B, BasicInstruction::IcmpCond::eq, reg1, 0, ++max_reg);
}

void single_float_add(int reg1, LLVMBlock B){
    //IRgenArithmeticF32ImmLeft(B, BasicInstruction::LLVMIROpcode::FADD, 0, reg1, ++max_reg);
    //好像没必要再写一条指令
}

void single_float_sub(int reg1, LLVMBlock B){
    //0-reg1，左操作数为立即数
    IRgenArithmeticF32ImmLeft(B, BasicInstruction::LLVMIROpcode::FSUB, 0, reg1, ++max_reg);
}

void single_float_not(int reg1, LLVMBlock B){
    //reg1==0
    IRgenFcmpImmRight(B, BasicInstruction::FcmpCond::OEQ, reg1, 0, ++max_reg);
}

void single_int_op(int reg1,std::string op, LLVMBlock B){
    if(op=="+"){
        single_int_add(reg1,B);
    }
    else if(op=="-"){
        single_int_sub(reg1,B);
    }
    else if(op=="!"){
        single_int_not(reg1,B);
    }
}

void single_float_op(int reg1,std::string op, LLVMBlock B){
    if(op=="+"){
        single_float_add(reg1,B);
    }
    else if(op=="-"){
        single_float_sub(reg1,B);
    }
    else if(op=="!"){
        single_float_not(reg1,B);
    }
}


void single_int(Expression a,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;
    single_int_op(reg1,op,B);
}

void single_float(Expression a,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;
    single_float_op(reg1,op,B);
}

void single_bool(Expression a,std::string op, LLVMBlock B){
    a->codeIR();
    int reg1 = max_reg;
    IRgenZextI1toI32(B, reg1, ++max_reg);//bool->int
    reg1 = max_reg;
    single_int_op(reg1,op,B);
}

void single_error(Expression a,std::string op, LLVMBlock B){
    assert(false);
}


void gen_single_IR(Expression a,std::string op, LLVMBlock B){
    if(a->attribute.T.type==Type::INT){
        single_int(a,op,B);
    }
    else if(a->attribute.T.type==Type::FLOAT){
        single_float(a,op,B);
    }
    else if(a->attribute.T.type==Type::BOOL){
        single_bool(a,op,B);
    }
    else if(a->attribute.T.type==Type::PTR||a->attribute.T.type==Type::VOID){
        single_error(a,op,B);
    }
}





/*
二元运算指令生成的伪代码：
    假设现在的语法树节点：AddExp_plus
    该语法树表示 addexp + mulexp

    addexp->codeIR()
    mulexp->codeIR()
    假设mulexp生成完后，我们应该在基本块B0继续插入指令。
    addexp的结果存储在r0寄存器中，mulexp的结果存储在r1寄存器中
    生成一条指令r2 = r0 + r1，并将该指令插入基本块B0末尾。
    标注后续应该在基本块B0插入指令，当前节点的结果寄存器为r2。
    (如果考虑支持浮点数，需要查看语法树节点的类型来判断此时是否需要隐式类型转换)
*/

/*
while语句指令生成的伪代码：
    while的语法树节点为while(cond)stmt

    假设当前我们应该在B0基本块开始插入指令
    新建三个基本块Bcond，Bbody，Bend
    在B0基本末尾插入一条无条件跳转指令，跳转到Bcond

    设置当前我们应该在Bcond开始插入指令
    cond->codeIR()    //在调用该函数前你可能需要设置真假值出口
    假设cond生成完后，我们应该在B1基本块继续插入指令，Bcond的结果为r0
    如果r0的类型不为bool，在B1末尾生成一条比较语句，比较r0是否为真。
    在B1末尾生成一条条件跳转语句，如果为真，跳转到Bbody，如果为假，跳转到Bend

    设置当前我们应该在Bbody开始插入指令
    stmt->codeIR()
    假设当stmt生成完后，我们应该在B2基本块继续插入指令
    在B2末尾生成一条无条件跳转语句，跳转到Bcond

    设置当前我们应该在Bend开始插入指令
*/

void __Program::codeIR() {
    AddLibFunctionDeclare();
    auto comp_vector = *comp_list;
    for (auto comp : comp_vector) {
        comp->codeIR();
    }
}

void Exp::codeIR() { addexp->codeIR(); }

void AddExp_plus::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    //就是说把这个指令往一个Block里面加
    //使用GetBlock()获取一个在函数I中编号为now_label的基本块, 该基本块必须已存在
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(addexp,mulexp,"+",now_Block);
}

void AddExp_sub::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(addexp,mulexp,"-",now_Block);
}

void MulExp_mul::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(mulexp,unary_exp,"*",now_Block);
}

void MulExp_div::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(mulexp,unary_exp,"/",now_Block);
}

void MulExp_mod::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(mulexp,unary_exp,"%",now_Block);
}

void RelExp_leq::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(relexp,addexp,"<=",now_Block);
}

void RelExp_lt::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(relexp,addexp,"<",now_Block);
}

void RelExp_geq::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(relexp,addexp,">=",now_Block);
}

void RelExp_gt::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(relexp,addexp,">",now_Block);
}

void EqExp_eq::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(eqexp,relexp,"==",now_Block);
}

void EqExp_neq::codeIR() { 
    //TODO("BinaryExp CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_binary_IR(eqexp,relexp,"!=",now_Block);
}

// short circuit &&
void LAndExp_and::codeIR() { 
    //TODO("LAndExpAnd CodeIR"); 
    //landexp && eqexp;
    
    //如果左表达式为真，跳到去检查右表达式
    LLVMBlock right_block=llvmIR.NewBlock(now_function,++max_label);
    landexp->true_label=right_block->block_id;
    //如果左表达式为假，那这整个&&表达式都为假
    landexp->false_label=this->false_label;
    landexp->codeIR();

    //获取左表达式的bool值（强制类型转换）+跳转语句
    LLVMBlock now_block=llvmIR.GetBlock(now_function,now_label);
    IRgenTypeConverse(now_block, landexp->attribute.T.type, Type::BOOL, max_reg);//生成一条类型转换的语句
    IRgenBrCond(now_block, max_reg, landexp->true_label, this->false_label);//生成一条条件跳转语句

    //现在就去右表达式的块了(能运行到这说明左表达式为1，那么右表达式的真假就和整个&&表达式一样)
    now_label=right_block->block_id;
    eqexp->true_label=this->true_label;
    eqexp->false_label=this->false_label;
    eqexp->codeIR();
    //仍然要往右表达式这个块里面加上强制类型转换+跳转语句
    //LLVMBlock B2 = llvmIR.GetBlock(now_function, now_label);
    //IRgenTypeConverse(B2, eqexp->attribute.T.type, Type::BOOL, max_reg);
    IRgenTypeConverse(right_block,eqexp->attribute.T.type,Type::BOOL,max_reg);//感觉这句有点没必要，if里面它判断cond了


}

// short circuit ||
void LOrExp_or::codeIR() { 
    //TODO("LOrExpOr CodeIR"); 
    //lorexp||landexp
    LLVMBlock right_block=llvmIR.NewBlock(now_function,++max_label);
    lorexp->true_label=this->true_label;
    lorexp->false_label=right_block->block_id;
    lorexp->codeIR();

    LLVMBlock now_block=llvmIR.GetBlock(now_function,now_label);
    IRgenTypeConverse(now_block, lorexp->attribute.T.type, Type::BOOL, max_reg);//生成一条类型转换的语句
    IRgenBrCond(now_block, max_reg, this->true_label, lorexp->false_label);//生成一条条件跳转语句

    now_label=right_block->block_id;
    landexp->true_label=this->true_label;
    landexp->false_label=this->false_label;
    landexp->codeIR();

    IRgenTypeConverse(right_block,landexp->attribute.T.type,Type::BOOL,max_reg);//感觉这句有点没必要，if里面它判断cond了

}

void ConstExp::codeIR() { addexp->codeIR(); }

//address of Lval
//// Reference: https://github.com/yuhuifishash/SysY/blob/master/ir_gen/IRgen.cc line220-line263
void Lval::codeIR() { 
    //TODO("Lval CodeIR"); 
    LLVMBlock now_block=llvmIR.GetBlock(now_function,now_label);
     std::vector<Operand> arrayindexs;
     //std::vector<int> lval_dims;
    if (dims != nullptr) {
        for (auto d : *dims) {
            d->codeIR();
            //lval_dims.push_back(d->attribute.V.val.IntVal);
            IRgenTypeConverse(now_block, d->attribute.T.type, Type::INT, max_reg);
            arrayindexs.push_back(GetNewRegOperand(max_reg));
        }
    } 
    
    Operand ptr_operand;
    VarAttribute lval_attribute;
    bool formal_array_tag = false;//判断该左值是不是用的形参的数组，因为形参数组第一维为为空，找地址时不一样
    //下面这行注释说明作用域是对的
    //std::cerr<<irgen_table.symbol_table.get_current_scope()<<std::endl;
    int alloca_reg = irgen_table.symbol_table.lookup(name);
    //std::cerr<<alloca_reg<<std::endl;
    if (alloca_reg != -1) {    // local, use var's alloca_reg
        //lval_attribute = semant_table.symbol_table.lookup_val(name);
        lval_attribute = irgen_table.RegTable[alloca_reg];
        //std::cerr<<"Lval:"<<lval_attribute.dims.size()<<std::endl;
        ptr_operand = GetNewRegOperand(alloca_reg);
        formal_array_tag = irgen_table.FormalArrayTable[alloca_reg];
        //std::cerr<<"jubu"<<lval_attribute.type<<std::endl;
    } else {    // global, use var's name
        ptr_operand = GetNewGlobalOperand(name->get_string());
        lval_attribute = semant_table.GlobalTable[name];
        //std::cerr<<"全局"<<lval_attribute.type<<std::endl;
       
    }
    //std::cerr<<"Lval:"<<lval_attribute.dims.size()<<std::endl;
    if (arrayindexs.empty() == false ||
        attribute.T.type == Type::PTR) {    // lval is array, first use getelementptr to get address
       /* if(attribute.T.type == Type::PTR){
            IRgenGetElementptrIndexI32(now_block, convertTyToLLVMType(lval_attribute.type), ++max_reg, ptr_operand, lval_attribute.dims, arrayindexs);
       }
       else{
            if (formal_array_tag) {             // formal array ptr, getelementptr first does not use 0
            IRgenGetElementptrIndexI32(now_block, convertTyToLLVMType(lval_attribute.type), ++max_reg, ptr_operand, lval_attribute.dims, arrayindexs);
            }
            else{
                arrayindexs.insert(arrayindexs.begin(), new ImmI32Operand(0));
            IRgenGetElementptrIndexI32(now_block, convertTyToLLVMType(attribute.T.type), ++max_reg, ptr_operand, lval_attribute.dims, arrayindexs);
            }        
       } */
       if (formal_array_tag) {             // formal array ptr, getelementptr first does not use 0
           IRgenGetElementptrIndexI32(now_block, convertTyToLLVMType(lval_attribute.type), ++max_reg, ptr_operand, lval_attribute.dims, arrayindexs);
            
        } else {    // array ptr, getelementptr first use 0
            arrayindexs.insert(arrayindexs.begin(), new ImmI32Operand(0));
            IRgenGetElementptrIndexI32(now_block, convertTyToLLVMType(lval_attribute.type), ++max_reg, ptr_operand, lval_attribute.dims, arrayindexs);
        }

        ptr_operand = GetNewRegOperand(max_reg);    // final address of ptr
    }
    ptr = ptr_operand;
    //这里缺失应该判断一下左值是否作为右值但是在参考代码中没有找到合理的给if_left赋值的逻辑
    if (attribute.T.type != Type::PTR) {    // not ptr, we need to use load to get the value of the array
        IRgenLoad(now_block, type2LLVMType(attribute.T.type), ++max_reg, ptr_operand);
    }

}

void FuncRParams::codeIR() {
    auto exp_vector = *params;
    for (auto exp : exp_vector) {
        exp->codeIR();
    }
    //TODO("FuncRParams CodeIR");
    }

void Func_call::codeIR() {
    /* LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    
    // 获取函数名和参数列
    std::string func_name = name->get_string();
    std::vector<std::pair<BasicInstruction::LLVMType, Operand>> args;
    
    // 获取实参列表并生成代码
    std::vector<Expression>* params = getParams();
    std::vector<int> param_regs; // 存储参数对应的寄存器号
    
    if(params && !params->empty()) {
        // 先生成所有参数的代码并保存寄存器号
        for(auto param : *params) {
            param->codeIR();
            param_regs.push_back(max_reg);
        }
        
        // 构建参数列表
        for(int i = 0; i < params->size(); i++) {
            Expression param = (*params)[i];
            BasicInstruction::LLVMType param_type = convertTyToLLVMType(param->attribute.T.type);
            args.push_back(std::make_pair(param_type, GetNewRegOperand(param_regs[i])));
        }
    }
    
    // 生成函数调用指令
    if(attribute.T.type == Type::VOID) {
        if(args.empty()) {
            // 无参数void函数
            IRgenCallVoidNoArgs(now_block, convertTyToLLVMType(attribute.T.type), func_name);
        } else {
            // 有参数void函数
            IRgenCallVoid(now_block, convertTyToLLVMType(attribute.T.type), args, func_name);
        }
    } else {
        // 有返回值的函数调用
        if(args.empty()) {
            // 无参数有返回值函数
            IRgenCallNoArgs(now_block, convertTyToLLVMType(attribute.T.type), ++max_reg, func_name);
        } else {
            // 有参数有返回值函数
            IRgenCall(now_block, convertTyToLLVMType(attribute.T.type), ++max_reg, args, func_name);
        }
    } */

    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    Type::ty return_type = semant_table.FunctionTable[name]->return_type;
    
    // 获取函数名和参数列
    std::string func_name = name->get_string();
    std::vector<std::pair<BasicInstruction::LLVMType, Operand>> args;
    std::vector<Expression>* params = getParams();
    if (params && !params->empty()) {
        //auto params = ((FuncRParams *)funcr_params)->params;
        auto fparams = semant_table.FunctionTable[name]->formals;
        assert(params->size() == fparams->size());
        for (int i = 0; i < (*params).size(); ++i) {
            auto param = (*params)[i];
            auto fparam = (*fparams)[i];
            param->codeIR();
            IRgenTypeConverse(now_block, param->attribute.T.type, fparam->attribute.T.type, max_reg);
            args.push_back({type2LLVMType(fparam->attribute.T.type), GetNewRegOperand(max_reg)});
        }
    } 


    // 生成函数调用指令
    if(return_type == Type::VOID) {
        if(funcr_params == nullptr) {
            // 无参数void函数
            IRgenCallVoidNoArgs(now_block, convertTyToLLVMType(return_type), func_name);
        } else {
            // 有参数void函数
            IRgenCallVoid(now_block, convertTyToLLVMType(return_type), args, func_name);
        }
    } else {
        // 有返回值的函数调用
        if(funcr_params == nullptr) {
            // 无参数有返回值函数
            IRgenCallNoArgs(now_block, convertTyToLLVMType(return_type), ++max_reg, func_name);
        } else {
            // 有参数有返回值函数
            IRgenCall(now_block, convertTyToLLVMType(return_type), ++max_reg, args, func_name);
        }
    }

}

//这里是单目运算
void UnaryExp_plus::codeIR() { 
    //TODO("UnaryExpPlus CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_single_IR(unary_exp,"+",now_Block);
}

void UnaryExp_neg::codeIR() { 
    //TODO("UnaryExpNeg CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_single_IR(unary_exp,"-",now_Block);
}

void UnaryExp_not::codeIR() { 
    //TODO("UnaryExpNot CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    gen_single_IR(unary_exp,"!",now_Block);
}

void IntConst::codeIR() { 
    //TODO("IntConst CodeIR");
    //val+0
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    IRgenArithmeticI32ImmAll(now_Block,BasicInstruction::LLVMIROpcode::ADD,val,0,++max_reg);
}

void FloatConst::codeIR() { 
    //TODO("FloatConst CodeIR"); 
    LLVMBlock now_Block=llvmIR.GetBlock(now_function,now_label);
    IRgenArithmeticF32ImmAll(now_Block,BasicInstruction::LLVMIROpcode::FADD,val,0,++max_reg);
}

void StringConst::codeIR() { 
    //TODO("StringConst CodeIR"); 
}

void PrimaryExp_branch::codeIR() { exp->codeIR(); }


/*
lval->codeIR();
get address of lval
exp->codeIR();
get value of exp
store
*/
//lval=exp
void assign_stmt::codeIR() { 
    //TODO("AssignStmt CodeIR"); 
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    lval->codeIR();
    exp->codeIR();
    IRgenTypeConverse(now_block, exp->attribute.T.type, lval->attribute.T.type, max_reg);
    IRgenStore(now_block, type2LLVMType(lval->attribute.T.type), max_reg, ((Lval *)lval)->ptr);
}

void expr_stmt::codeIR() { exp->codeIR(); }

void block_stmt::codeIR() { 
    
    irgen_table.symbol_table.enter_scope();
    b->codeIR();
    irgen_table.symbol_table.exit_scope();
    
    //TODO("BlockStmt CodeIR"); 
    }

void ifelse_stmt::codeIR() { 
    //TODO("IfElseStmt CodeIR"); 
    LLVMBlock if_block=llvmIR.NewBlock(now_function,++max_label);
    int if_label=if_block->block_id;
    LLVMBlock else_block=llvmIR.NewBlock(now_function,++max_label);
    int else_label=else_block->block_id;
    LLVMBlock end_block=llvmIR.NewBlock(now_function,++max_label);
    int end_label=end_block->block_id;

    Cond->true_label = if_label;
    Cond->false_label = else_label;
    Cond->codeIR();
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    IRgenTypeConverse(now_block, Cond->attribute.T.type, Type::BOOL, max_reg);
    IRgenBrCond(now_block, max_reg, if_label, else_label);

    //这是条件为真，进到if_stmt块里
    now_label = if_label;
    ifstmt->codeIR();
    //IRgenBRUnCond(if_block,end_label);//无条件跳转到end
    LLVMBlock B2 = llvmIR.GetBlock(now_function, now_label);
    IRgenBRUnCond(B2, end_label);

    now_label = else_label;
    elsestmt->codeIR();
    //IRgenBRUnCond(else_block,end_label);//无条件跳转到end
    LLVMBlock B3 = llvmIR.GetBlock(now_function, now_label);
    IRgenBRUnCond(B3, end_label);

    now_label=end_label;
}

void if_stmt::codeIR() { 
    //TODO("IfStmt CodeIR"); 
    //if(Cond) if_stmt 
    LLVMBlock if_block=llvmIR.NewBlock(now_function,++max_label);
    int if_label=if_block->block_id;
    LLVMBlock end_block=llvmIR.NewBlock(now_function,++max_label);
    int end_label=end_block->block_id;

    //要想进到if，要先把条件cond的中间代码生成出来，根据条件真假确定跳转到哪
    Cond->true_label = if_label;
    Cond->false_label = end_label;
    Cond->codeIR();
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    IRgenTypeConverse(now_block, Cond->attribute.T.type, Type::BOOL, max_reg);
    IRgenBrCond(now_block, max_reg, if_label, end_label);

    //这是条件为真，进到if_stmt块里
    now_label = if_label;
    ifstmt->codeIR();
    //IRgenBRUnCond(if_block,end_label);//无条件跳转到end
    LLVMBlock B2 = llvmIR.GetBlock(now_function, now_label);
    IRgenBRUnCond(B2, end_label);

    now_label = end_label;
}

void while_stmt::codeIR() { 
    //while(Cond) body
    LLVMBlock cond_block=llvmIR.NewBlock(now_function,++max_label);
    int cond_label=cond_block->block_id;
    LLVMBlock body_block=llvmIR.NewBlock(now_function,++max_label);
    int body_label=body_block->block_id;
    LLVMBlock end_block=llvmIR.NewBlock(now_function,++max_label);
    int end_label=end_block->block_id;
    
    // 保存循环的 cond_label 和 end_label
    loop_labels.push({cond_label, end_label});

    //先无条件跳转到循环判断处
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    IRgenBRUnCond(now_block,cond_label);

    now_label=cond_label;
    Cond->true_label=body_label;
    Cond->false_label=end_label;
    Cond->codeIR();
    
    //IRgenTypeConverse(cond_block, Cond->attribute.T.type, Type::BOOL, max_reg);
    //IRgenBrCond(cond_block, max_reg, body_label, end_label);
    //经历cond之后，now_label可能会改变
    LLVMBlock B2 = llvmIR.GetBlock(now_function, now_label);
    IRgenTypeConverse(B2, Cond->attribute.T.type, Type::BOOL, max_reg);
    IRgenBrCond(B2, max_reg, body_label, end_label);

    now_label=body_label;
    body->codeIR();
    //循环体运行结束就跳到开头条件判断处
    //IRgenBRUnCond(body_block,cond_label);
    LLVMBlock B3 = llvmIR.GetBlock(now_function, now_label);
    IRgenBRUnCond(B3, cond_label);

    now_label=end_label;  
    
    loop_labels.pop(); // 退出循环时弹出标签
}

void continue_stmt::codeIR() {
    if (!loop_labels.empty()) {
        LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
        IRgenBRUnCond(now_block, loop_labels.top().first); // 跳转到循环开始
        now_label = llvmIR.NewBlock(now_function, ++max_label)->block_id;
    }
}

void break_stmt::codeIR() {
    if (!loop_labels.empty()) {
        LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
        IRgenBRUnCond(now_block, loop_labels.top().second); // 跳转到循环结束
        now_label = llvmIR.NewBlock(now_function, ++max_label)->block_id;
    }
}

// 添加一个辅助函数来转换类型
Type::ty convertLLVMTypeToTy(BasicInstruction::LLVMType type) {
    switch(type) {
        case BasicInstruction::I32: return Type::INT;
        case BasicInstruction::FLOAT32: return Type::FLOAT;
        case BasicInstruction::I1: return Type::BOOL;
        case BasicInstruction::VOID: return Type::VOID;
        case BasicInstruction::PTR: return Type::PTR;
        default: return Type::VOID;
    }
}

void return_stmt::codeIR() { 
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    return_exp->codeIR();
    //int reg = max_reg;
    
    // 转换类型后再传入
    IRgenTypeConverse(now_block, return_exp->attribute.T.type, 
                     convertLLVMTypeToTy(now_function->GetReturnType()), max_reg);
    
    // 生成return指令
    IRgenRetReg(now_block, now_function->GetReturnType(), max_reg);
}

void return_stmt_void::codeIR() { 
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    IRgenRetVoid(now_block);
}

void ConstInitVal::codeIR() {
    // 处理常量初始化列表
    if(initval) {
        for(auto init : *initval) {
            init->codeIR();
        }
    }
}

void ConstInitVal_exp::codeIR() {
    // 处理常量表达式初始化
    exp->codeIR();
}

void VarInitVal::codeIR() {
    // 处理变量初始化列表
    if(initval) {
        for(auto init : *initval) {
            init->codeIR();
        }
    }
}

void VarInitVal_exp::codeIR() {
    // 处理变量表达式初始化
    exp->codeIR();
}

void VarDef_no_init::codeIR() {
    
   if (GlobalTag == false) {
        VarAttribute val;
        Operand val_operand;
        val.type = attribute.T.type;
        LLVMBlock zero_block = llvmIR.GetBlock(now_function, 0);//函数零号入口块
        LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
            int alloca_reg = ++max_reg;
        if(dims==nullptr){
            IRgenAlloca(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg); 
            irgen_table.RegTable[alloca_reg] = val;           
            if (val.type == Type::INT) {
                    IRgenArithmeticI32ImmAll(now_block, BasicInstruction::LLVMIROpcode::ADD, 0, 0, ++max_reg);
                    val_operand = GetNewRegOperand(max_reg);
                } else if (val.type == Type::FLOAT) {
                    IRgenArithmeticF32ImmAll(now_block, BasicInstruction::LLVMIROpcode::FADD, 0, 0, ++max_reg);
                    val_operand = GetNewRegOperand(max_reg);
                }        
            IRgenStore(now_block, convertTyToLLVMType(attribute.T.type), val_operand, GetNewRegOperand(alloca_reg));           
        }
        else{

            // 计算数组维度
            /*
            这里有两种方案，一种是for循环遍历dims，另一种是直接从符号表中获取,不知道哪种对
            */
            std::vector<int> array_dims;
            for(auto dim : *dims) {              
                array_dims.push_back(dim->attribute.V.val.IntVal);
                val.dims.push_back(dim->attribute.V.val.IntVal);
            }irgen_table.RegTable[alloca_reg] = val;
            //array_dims=semant_table.symbol_table.lookup_val(name).dims;
            // 分配数组空间
            IRgenAllocaArray(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg, array_dims);

        }  irgen_table.symbol_table.add_Symbol(name, alloca_reg);      
    }else{
        Instruction globalDecl;
        if(dims==nullptr){
            
            globalDecl = new GlobalVarDefineInstruction(name->get_string(),convertTyToLLVMType(attribute.T.type) , nullptr);
            
        }
        else{
            // 处理全局数组变量
            /*std::vector<int> array_dims;
            for(auto dim : *dims) {
                
                //array_dims.push_back(dim->attribute.V.val.IntVal);
            }*/
            
            globalDecl = new GlobalVarDefineInstruction(name->get_string(), convertTyToLLVMType(attribute.T.type), semant_table.GlobalTable[name]);
            
        }llvmIR.global_def.push_back(globalDecl);
    }
}

void VarDef::codeIR() {
    if (GlobalTag == false) { 
        VarAttribute val;
        val.type = attribute.T.type;
        // 处理带初始化的变量定义
        LLVMBlock zero_block = llvmIR.GetBlock(now_function, 0);//函数零号入口块
        LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
        int alloca_reg = ++max_reg;
        //std::cerr<<"exist?:"<<semant_table.symbol_table.lookup(name)<<std::endl;
        //std::cerr<<" scope: "<<attribute.T.type<<std::endl;
        
        if(dims==nullptr){
            IRgenAlloca(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg); 
            //这个if(init)有必要吗？本来这个类就是带初始化的。    
            //对，没必要，所以删了
        
                init->codeIR();
                IRgenTypeConverse(now_block, init->attribute.T.type, attribute.T.type, max_reg);
                int init_reg = max_reg;           
                // 储存初始值
                if(alloca_reg!=-1){
                IRgenStore(now_block, 
                        convertTyToLLVMType(attribute.T.type), 
                        init_reg, 
                        GetNewRegOperand(alloca_reg));
                irgen_table.RegTable[alloca_reg] = val;}
                else std::cout<<"irgen.cc,vardef,alloca_reg==-1"<<std::endl;
            
        }else{
            // 计算数组维度
                /*
                这里有两种方案，一种是for循环遍历dims，另一种是直接从符号表中获取,不知道哪种对
                */
                int array_sz = 1;
                std::vector<int> array_dims;
                for(auto dim : *dims) {              
                    array_dims.push_back(dim->attribute.V.val.IntVal);
                    array_sz *= dim->attribute.V.val.IntVal;
                    val.dims.push_back(dim->attribute.V.val.IntVal);
                }
                //array_dims=semant_table.symbol_table.lookup_val(name).dims;
                // 分配数组空间
                irgen_table.RegTable[alloca_reg] = val;
                IRgenAllocaArray(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg, array_dims);
                CallInstruction *memsetCall = new CallInstruction(convertTyToLLVMType(Type::VOID), nullptr, std::string("llvm.memset.p0.i32"));
                    memsetCall->push_back_Parameter(convertTyToLLVMType(Type::PTR), GetNewRegOperand(alloca_reg));    // array address
                    memsetCall->push_back_Parameter(BasicInstruction::LLVMType::I8, new ImmI32Operand(0));
                    memsetCall->push_back_Parameter(convertTyToLLVMType(Type::INT), new ImmI32Operand(array_sz * sizeof(int)));
                    memsetCall->push_back_Parameter(convertTyToLLVMType(Type::BOOL), new ImmI32Operand(0));
                    llvmIR.function_block_map[now_function][now_label]->InsertInstruction(1, memsetCall);
                RecursiveArrayInitIR(now_block, array_dims, alloca_reg, init, 0, array_sz - 1, 0, attribute.T.type);
        }
            // 将局部变量寄存器号存入符号表
            irgen_table.symbol_table.add_Symbol(name, alloca_reg);        
    }
    else{
        Instruction globalDecl;

        if(dims==nullptr){
            if (convertTyToLLVMType(attribute.T.type) == BasicInstruction::I32) {
                if(init->attribute.T.type==Type::INT){
                    globalDecl =new GlobalVarDefineInstruction(name->get_string(),BasicInstruction::I32, new ImmI32Operand(init->attribute.V.val.IntVal));
                }
                else if(init->attribute.T.type==Type::FLOAT){
                    globalDecl =new GlobalVarDefineInstruction(name->get_string(),BasicInstruction::I32, new ImmI32Operand((int)(init->attribute.V.val.FloatVal)));
                }
                
            } else if (convertTyToLLVMType(attribute.T.type) == BasicInstruction:: FLOAT32) {
                if(init->attribute.T.type==Type::INT){
                    globalDecl = new GlobalVarDefineInstruction(name->get_string(), BasicInstruction:: FLOAT32,new ImmF32Operand((int)(init->attribute.V.val.IntVal)));
                }
                else if(init->attribute.T.type==Type::FLOAT){
                    globalDecl = new GlobalVarDefineInstruction(name->get_string(), BasicInstruction:: FLOAT32,new ImmF32Operand(init->attribute.V.val.FloatVal));
                }
            }
        }else{
            // 处理全局数组变量
            /*for(auto dim : *dims) {
                dim->codeIR();
                //array_dims.push_back(dim->attribute.V.val.IntVal);
            }*/
            //array_dims=semant_table.symbol_table.lookup_val(name).dims;
            // 分配数组空间
            globalDecl = new GlobalVarDefineInstruction(name->get_string(), convertTyToLLVMType(attribute.T.type), semant_table.GlobalTable[name]);
        }   
        llvmIR.global_def.push_back(globalDecl);
    }
}

void ConstDef::codeIR() {
    if (GlobalTag == false) {
        VarAttribute val;
        val.type = attribute.T.type;   
        // 处理带初始化的变量定义
        LLVMBlock zero_block = llvmIR.GetBlock(now_function, 0);//函数零号入口块
        LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
        int alloca_reg = ++max_reg;
        if(dims==nullptr){
            //std::cerr<<"exist?:"<<semant_table.symbol_table.lookup(name)<<std::endl;
            //std::cerr<<" scope: "<<attribute.T.type<<std::endl;
            IRgenAlloca(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg); 
            // 不是数组 

            init->codeIR();
            IRgenTypeConverse(now_block, init->attribute.T.type, attribute.T.type, max_reg);
            int init_reg = max_reg;           
            // 储存初始值
            IRgenStore(now_block, 
                      convertTyToLLVMType(attribute.T.type), 
                      init_reg, 
                      GetNewRegOperand(alloca_reg));
            irgen_table.RegTable[alloca_reg] = val;
        }
        else{
            // 处理局部const数组变量
        // 计算数组维度
            /*
            这里有两种方案，一种是for循环遍历dims，另一种是直接从符号表中获取,不知道哪种对还是都对
            */
            int array_sz = 1;
            std::vector<int> array_dims;
            for(auto dim : *dims) {              
                array_dims.push_back(dim->attribute.V.val.IntVal);
                array_sz *= dim->attribute.V.val.IntVal;
                val.dims.push_back(dim->attribute.V.val.IntVal);
            }
            //array_dims=semant_table.symbol_table.lookup_val(name).dims;
            // 分配数组空间
            irgen_table.RegTable[alloca_reg] = val;
            IRgenAllocaArray(zero_block, convertTyToLLVMType(attribute.T.type), alloca_reg, array_dims);
            CallInstruction *memsetCall = new CallInstruction(convertTyToLLVMType(Type::VOID), nullptr, std::string("llvm.memset.p0.i32"));
                memsetCall->push_back_Parameter(convertTyToLLVMType(Type::PTR), GetNewRegOperand(alloca_reg));    // array address
                memsetCall->push_back_Parameter(BasicInstruction::LLVMType::I8, new ImmI32Operand(0));
                memsetCall->push_back_Parameter(convertTyToLLVMType(Type::INT), new ImmI32Operand(array_sz * sizeof(int)));
                memsetCall->push_back_Parameter(convertTyToLLVMType(Type::BOOL), new ImmI32Operand(0));
                llvmIR.function_block_map[now_function][now_label]->InsertInstruction(1, memsetCall);
            RecursiveArrayInitIR(now_block, array_dims, alloca_reg, init, 0, array_sz - 1, 0, attribute.T.type);
        }
        // 将局部变量寄存器号存入符号表
        irgen_table.symbol_table.add_Symbol(name, alloca_reg);        
    }
    else{
        //处理全局常量
        Instruction globalDecl;
        if(dims==nullptr){//不是数组
           /*  if (convertTyToLLVMType(attribute.T.type) == BasicInstruction::I32) {
                globalDecl =new GlobalVarDefineInstruction(name->get_string(),BasicInstruction::I32, new ImmI32Operand(init->attribute.V.val.IntVal));
            } else if (convertTyToLLVMType(attribute.T.type) == BasicInstruction:: FLOAT32) {
                globalDecl = new GlobalVarDefineInstruction(name->get_string(), BasicInstruction:: FLOAT32,
                                                            new ImmF32Operand(init->attribute.V.val.FloatVal));
            }   */
            if (convertTyToLLVMType(attribute.T.type) == BasicInstruction::I32) {
                if(init->attribute.T.type==Type::INT){
                    globalDecl =new GlobalVarDefineInstruction(name->get_string(),BasicInstruction::I32, new ImmI32Operand(init->attribute.V.val.IntVal));
                }
                else if(init->attribute.T.type==Type::FLOAT){
                    globalDecl =new GlobalVarDefineInstruction(name->get_string(),BasicInstruction::I32, new ImmI32Operand((int)(init->attribute.V.val.FloatVal)));
                }
                
            } else if (convertTyToLLVMType(attribute.T.type) == BasicInstruction:: FLOAT32) {
                if(init->attribute.T.type==Type::INT){
                    globalDecl = new GlobalVarDefineInstruction(name->get_string(), BasicInstruction:: FLOAT32,new ImmF32Operand((int)(init->attribute.V.val.IntVal)));
                }
                else if(init->attribute.T.type==Type::FLOAT){
                    globalDecl = new GlobalVarDefineInstruction(name->get_string(), BasicInstruction:: FLOAT32,new ImmF32Operand(init->attribute.V.val.FloatVal));
                }
            }
        }
        else{
            // 处理全局const数组变量
                      
            globalDecl = new GlobalVarDefineInstruction(name->get_string(), convertTyToLLVMType(attribute.T.type), semant_table.GlobalTable[name]);
        }
        llvmIR.global_def.push_back(globalDecl);
    }
}

void VarDecl::codeIR() {
    // 处理变量声明
    for(auto def : *var_def_list) {
        def->codeIR();
    }
}

void ConstDecl::codeIR() {
    // 处理常量声明
    for(auto def : *var_def_list) {
        def->codeIR();
    }
}

void BlockItem_Decl::codeIR() {
    // 处理块内声明语句
    decl->codeIR();
}

void BlockItem_Stmt::codeIR() { 
    stmt->codeIR();
    //TODO("BlockItemStmt CodeIR"); 
    }

void __Block::codeIR() { 
    irgen_table.symbol_table.enter_scope();
    auto item_vector = *item_list;
    for (auto item : item_vector) {
        item->codeIR();
    }
    irgen_table.symbol_table.exit_scope();
    //TODO("Block CodeIR"); 
    }

void __FuncFParam::codeIR() {
    // 处理函数参数
    LLVMBlock now_block = llvmIR.GetBlock(now_function, now_label);
    int param_reg = ++max_reg;
    int alloca_reg = ++max_reg;
    if (dims != nullptr) {
        // 数组参数
        // 为参数分配空间
         std::vector<int> array_dims;
        for(auto dim : *dims) {
                //dim->codeIR();
                array_dims.push_back(dim->attribute.V.val.IntVal);
            }
        IRgenAllocaArray(now_block,convertTyToLLVMType(attribute.T.type), alloca_reg, array_dims);
        
        // 存储参数值
        
        //IRgenStore(now_block, BasicInstruction::PTR, param_reg, GetNewRegOperand(alloca_reg));
        
        // 将参数添加到符号表
        irgen_table.symbol_table.add_Symbol(name, alloca_reg);
        
    } else {
        // 普通参数
        now_function->InsertFormal(type2LLVMType(type_decl));
        // 为参数分配空间
        IRgenAlloca(now_block, convertTyToLLVMType(attribute.T.type), alloca_reg);        
        // 存储参数值  
        IRgenStore(now_block, convertTyToLLVMType(attribute.T.type), param_reg, GetNewRegOperand(alloca_reg));
        
        // 将参数添加到符号表
        irgen_table.symbol_table.add_Symbol(name, alloca_reg);
    }
}


//每个基本块都要有一个跳转语句，如果没有要给它加上
void AddNoReturnBlock(Type::ty return_ty) {
    //每个基本块都要有一个跳转语句
    for (auto block : llvmIR.function_block_map[now_function]) {
        LLVMBlock B = block.second;
        if ((B->Instruction_list.empty()) || (((B->Instruction_list.back())->GetOpcode()!=BasicInstruction::RET)&&((B->Instruction_list.back())->GetOpcode()!=BasicInstruction::BR_COND&&(B->Instruction_list.back())->GetOpcode()!=BasicInstruction::BR_UNCOND) )) {
            if (return_ty == Type::VOID) {
                IRgenRetVoid(B);
            } else if (return_ty == Type::INT) {
                IRgenRetImmInt(B, BasicInstruction::I32, 0);
            } else if (return_ty == Type::FLOAT) {
                IRgenRetImmFloat(B, BasicInstruction::FLOAT32, 0);
            }
        }
    }
}





void __FuncDef::codeIR() {
    // 进入新作用域
    irgen_table.symbol_table.enter_scope();
    // 创建新函数并设置返回值类型
    FuncDefInstruction new_func_def = new FunctionDefineInstruction(convertTyToLLVMType(return_type), name->get_string());
    //llvmIR.NewFunction(new FunctionDefineInstruction(convertTyToLLVMType(return_type), name->get_string()));
    //now_function=llvmIR.function_block_map.rbegin()->first;
    //std::cerr<<name->get_string()<<std::endl;
    max_reg = -1;
    irgen_table.RegTable.clear();
    irgen_table.FormalArrayTable.clear();
    now_label = 0;
    max_label = -1;
    now_function = new_func_def;

    llvmIR.NewFunction(now_function);
    LLVMBlock entry = llvmIR.NewBlock(now_function, ++max_label);
    // 创建入口基本块
    //++max_label;
    //LLVMBlock entry = llvmIR.NewBlock(now_function, max_label);
    
    now_label = max_label;
    //std::cerr<<"now_label"<<now_label<<std::endl;
    
    //reference:https://github.com/yuhuifishash/SysY/blob/master/ir_gen/IRgen.cc line741-line766
    // 处理函数参数
    if(formals) {
        auto formal_vector = *formals;
        max_reg = formal_vector.size() - 1;
        for (int i = 0; i < formal_vector.size(); ++i) {
            auto formal = formal_vector[i];
            VarAttribute val;
            val.type = formal->type_decl;
            if (formal->dims != nullptr) {    //参数是个数组
                // 对于数组参数，它假设数组地址不会被修改，因此不需要额外的alloca指令
                now_function->InsertFormal(BasicInstruction::PTR);

                for (int i = 1; i < formal->dims->size(); ++i) {    // in IRgen, we ignore the first dim of the
                                                                    // formal
                    auto d = formal->dims->at(i);
                    val.dims.push_back(d->attribute.V.val.IntVal);
                }

                irgen_table.FormalArrayTable[i] = 1;
                irgen_table.symbol_table.add_Symbol(formal->name, i);
                irgen_table.RegTable[i] = val;

                
            } else {    // 参数不是数组
                now_function->InsertFormal(type2LLVMType(formal->type_decl));
                IRgenAlloca(entry, type2LLVMType(formal->type_decl), ++max_reg);
                IRgenStore(entry, type2LLVMType(formal->type_decl), GetNewRegOperand(i), GetNewRegOperand(max_reg));
                irgen_table.symbol_table.add_Symbol(formal->name, max_reg);
                irgen_table.RegTable[max_reg] = val;
            }
        }
        
    }



    
    // 处理函数体
    block->codeIR();

    AddNoReturnBlock(return_type);//参考源代码
    max_label_map[now_function] = max_label;
    max_reg_map[now_function] = max_reg;
    // 退出作用域
    irgen_table.symbol_table.exit_scope();
}

void CompUnit_Decl::codeIR() {
    // 处理全局声明
    decl->GlobalTag = true; // 标记为全局声明
    decl->codeIR();
}

void CompUnit_FuncDef::codeIR() { func_def->codeIR(); }

//函数实现了添加一系列库函数声明到llvmIR实例中
void AddLibFunctionDeclare() {
    FunctionDeclareInstruction *getint = new FunctionDeclareInstruction(BasicInstruction::I32, "getint");
    llvmIR.function_declare.push_back(getint);

    FunctionDeclareInstruction *getchar = new FunctionDeclareInstruction(BasicInstruction::I32, "getch");
    llvmIR.function_declare.push_back(getchar);

    FunctionDeclareInstruction *getfloat = new FunctionDeclareInstruction(BasicInstruction::FLOAT32, "getfloat");
    llvmIR.function_declare.push_back(getfloat);

    FunctionDeclareInstruction *getarray = new FunctionDeclareInstruction(BasicInstruction::I32, "getarray");
    getarray->InsertFormal(BasicInstruction::PTR);
    llvmIR.function_declare.push_back(getarray);

    FunctionDeclareInstruction *getfloatarray = new FunctionDeclareInstruction(BasicInstruction::I32, "getfarray");
    getfloatarray->InsertFormal(BasicInstruction::PTR);
    llvmIR.function_declare.push_back(getfloatarray);

    FunctionDeclareInstruction *putint = new FunctionDeclareInstruction(BasicInstruction::VOID, "putint");
    putint->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(putint);

    FunctionDeclareInstruction *putch = new FunctionDeclareInstruction(BasicInstruction::VOID, "putch");
    putch->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(putch);

    FunctionDeclareInstruction *putfloat = new FunctionDeclareInstruction(BasicInstruction::VOID, "putfloat");
    putfloat->InsertFormal(BasicInstruction::FLOAT32);
    llvmIR.function_declare.push_back(putfloat);

    FunctionDeclareInstruction *putarray = new FunctionDeclareInstruction(BasicInstruction::VOID, "putarray");
    putarray->InsertFormal(BasicInstruction::I32);
    putarray->InsertFormal(BasicInstruction::PTR);
    llvmIR.function_declare.push_back(putarray);

    FunctionDeclareInstruction *putfarray = new FunctionDeclareInstruction(BasicInstruction::VOID, "putfarray");
    putfarray->InsertFormal(BasicInstruction::I32);
    putfarray->InsertFormal(BasicInstruction::PTR);
    llvmIR.function_declare.push_back(putfarray);

    FunctionDeclareInstruction *starttime = new FunctionDeclareInstruction(BasicInstruction::VOID, "_sysy_starttime");
    starttime->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(starttime);

    FunctionDeclareInstruction *stoptime = new FunctionDeclareInstruction(BasicInstruction::VOID, "_sysy_stoptime");
    stoptime->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(stoptime);

    // 一些llvm自带的函数，也许会为你的优化提供帮助
    FunctionDeclareInstruction *llvm_memset =
    new FunctionDeclareInstruction(BasicInstruction::VOID, "llvm.memset.p0.i32");
    llvm_memset->InsertFormal(BasicInstruction::PTR);
    llvm_memset->InsertFormal(BasicInstruction::I8);
    llvm_memset->InsertFormal(BasicInstruction::I32);
    llvm_memset->InsertFormal(BasicInstruction::I1);
    llvmIR.function_declare.push_back(llvm_memset);

    FunctionDeclareInstruction *llvm_umax = new FunctionDeclareInstruction(BasicInstruction::I32, "llvm.umax.i32");
    llvm_umax->InsertFormal(BasicInstruction::I32);
    llvm_umax->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(llvm_umax);

    FunctionDeclareInstruction *llvm_umin = new FunctionDeclareInstruction(BasicInstruction::I32, "llvm.umin.i32");
    llvm_umin->InsertFormal(BasicInstruction::I32);
    llvm_umin->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(llvm_umin);

    FunctionDeclareInstruction *llvm_smax = new FunctionDeclareInstruction(BasicInstruction::I32, "llvm.smax.i32");
    llvm_smax->InsertFormal(BasicInstruction::I32);
    llvm_smax->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(llvm_smax);

    FunctionDeclareInstruction *llvm_smin = new FunctionDeclareInstruction(BasicInstruction::I32, "llvm.smin.i32");
    llvm_smin->InsertFormal(BasicInstruction::I32);
    llvm_smin->InsertFormal(BasicInstruction::I32);
    llvmIR.function_declare.push_back(llvm_smin);
}
